namespace Yaaf.WP7.NativeAccess.Registry.Internals.AllDevices
{
    using System;
    using System.Text;

    using Yaaf.WP7.NativeAccess.Helper;
    using Yaaf.WP7.NativeAccess.Provision;

    /// <summary>
    /// 
    /// </summary>
    public class ProvisionRegistryBase : RegistryBase
    {
        public override void SetValue(RootKey root, string subKey, string valueName, object value, RegistryValueKind valueKind)
        {
            var keyPath = GetKeyPath(root, subKey);
            if (valueKind == RegistryValueKind.Unknown)
            {
                valueKind = CalculateValueKind(value);
            }

            var reg = new ProvisionXmlRegistry();
            switch (valueKind)
            {
                case RegistryValueKind.DWord:
                    reg.AddSetRegistryKeyOperation(keyPath, valueName, value.ToString(), ProvisionXmlRegistryValueKind.Integer);
                    break;
                case RegistryValueKind.String:
                    reg.AddSetRegistryKeyOperation(keyPath, valueName, value.ToString(), ProvisionXmlRegistryValueKind.String);
                    break;
                case RegistryValueKind.Binary:
                    reg.AddSetRegistryKeyOperation(keyPath, valueName, Convert.ToBase64String((byte[])value), ProvisionXmlRegistryValueKind.Binary);
                    break;
                case RegistryValueKind.MultiString:
                    reg.AddSetRegistryKeyOperation(keyPath, valueName, ConvertArrayToMultiString((string[])value), ProvisionXmlRegistryValueKind.Multiplestring);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("valueKind");
            }

            ProvisionXml.Provision(reg.ToString());
        }

        private static string ConvertArrayToMultiString(string[] value)
        {
            var builder = new StringBuilder();
            foreach (var s in value)
            {
                builder.Append(s + "&#xF000;");
            }
            builder.Append("&#xF000;");
            return builder.ToString();
        }

        private static RegistryValueKind CalculateValueKind(object value)
        {
            if (value is int)
            {
                return RegistryValueKind.DWord;
            }
            if (!(value is Array))
            {
                return RegistryValueKind.String;
            }
            if (value is byte[])
            {
                return RegistryValueKind.Binary;
            }
            if (!(value is string[]))
            {
                throw new ArgumentException("Arg_RegSetBadArrType");
            }
            return RegistryValueKind.MultiString;
        }

        public override void DeleteKey(RootKey root, string subKey)
        {
            var unified = GetKeyPath(root, subKey);
            var reg = new ProvisionXmlRegistry();
            reg.AddDeleteKeyOperation(unified);
            ProvisionXml.Provision(reg.ToString());
        }

        public override void DeleteValue(RootKey root, string subKey, string valueName)
        {
            var keyPath = GetKeyPath(root, subKey);
            var reg = new ProvisionXmlRegistry();
            reg.AddDeleteValueOperation(keyPath, valueName);

            ProvisionXml.Provision(reg.ToString());
        }

        private static string GetKeyPath(RootKey root, string subKey)
        {
            return NativeAccess.Registry.Registry.ToShortRepresentation(root) + "\\" + subKey;
        }
    }
}